#include <csignal>
#include <cstdlib>
#include <stdint.h>
#include <event.h>

#include "signals.h"
#include <logger.h>
#include "shellcmd.h"

namespace utils {
struct event_base *base_handler();
void signal_cb(evutil_socket_t fd,short event,void *arg);

MessageQueue::MessageQueue():
    m_ebase(NULL)
{
}

MessageQueue::~MessageQueue()
{
}

Json::Value MessageQueue::Execute(int mode, const string &script)
{
    struct event *evn;
//    struct event *ev;

    m_ebase = event_base_new();
    m_mode = mode;
    m_strscript = script;

//    ev = event_new(base_handler(),-1,EV_TIMEOUT,
//                 event_cb,this);

    evn = event_new(m_ebase,-1,EV_TIMEOUT,
                    event_cb,this);
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 1000;
//    event_add(evn,&tv);
//    tv1.tv_sec = 0;
//    tv1.tv_usec = 500000;
    event_add(evn,&tv);
    event_base_dispatch(m_ebase);
    event_base_free(m_ebase);
//    event_del(ev);
//    event_free(ev);
    event_free(evn);
    return m_jsonResult;
}

Json::Value MessageQueue::executeScript(int mode, const string &script)
{
    Json::Value result;
    if (mode == 0) {
        //get
        ShellCmd shellCmd;
        string res = shellCmd.ShellGet(script.c_str());
        if (res.empty())
        {
            return result;
        }
        Json::CharReaderBuilder builder;
        Json::CharReader *reader = builder.newCharReader();
        string err;
        const char *pStr = res.c_str();
        int length = res.length();
        if (!reader->parse(pStr,pStr+length,&result,&err)) {
            LOG_ERR("parse error:%s",err.c_str());
            delete reader;
            return result;
        }
        delete reader;
        return result;
    }
    else if (mode == 1){
        ShellCmd shellCmd;
        int res = shellCmd.ShellSet(script.c_str());
        result = res;
        return result;
    }
    else {
        ShellCmd shellCmd;
        string res = shellCmd.ShellGet(script.c_str());
        result = res;
        return result;
    }
}

void MessageQueue::doEvent()
{
    m_jsonResult = executeScript(
                m_mode,
                m_strscript);

    event_base_loopbreak(m_ebase);
}

void MessageQueue::event_timeout(int fd, short event, void *arg)
{
    LOG_TRACE();
    struct event_base *base = (struct event_base*)arg;
    event_base_loopbreak(base);
}

void MessageQueue::event_cb(int fd, short event, void *arg)
{
    LOG_TRACE();
    MessageQueue *msgQue = static_cast<MessageQueue*>(arg);
    msgQue->doEvent();
}

BOOL WaitTerminationSignals(sighandler_t sig_handler)
{
    LOG_TRACE();
    struct event_base *base = base_handler();
    struct event *signal_int = evsignal_new(base,SIGINT,signal_cb,base);/*event_self_cbarg()*/
    if(!signal_int || event_add(signal_int,NULL) < 0)
    {
        LOG_ERR("create or add signal_int failed");
        return false;
    }
    event_dispatch();
    event_del(signal_int);
    sig_handler(event_get_signal(signal_int));

    event_free(signal_int);
//    event_base_free(base);

    return true;
}

struct event_base *base_handler()
{
    static struct event_base *s_ebase = NULL;
    if (s_ebase == NULL)
        s_ebase = event_init();
    return s_ebase;
}

void signal_cb(evutil_socket_t fd,short event,void *arg)
{
    LOG_TRACE();
    struct event_base *base = (struct event_base *)arg;
    event_base_loopbreak(base);
}

void event_cb(evutil_socket_t fd,short event,void *arg)
{
    LOG_TRACE();
    struct event_base *base = (struct event_base *)arg;
    event_base_loopbreak(base);
}

}
